package com.chu.cloud.api.service;

import com.chu.cloud.dto.SeckillDto;
import com.chu.cloud.dto.order.OrderResult;
import com.chu.cloud.dto.order.SeckillOrderCreateDto;
import com.chu.cloud.enums.RedisKeyPrefix;
import com.chu.cloud.stream.channel.SeckillExecuteProcessor;
import com.chu.cloud.util.ChuException;
import com.chu.cloud.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author: Tianshu.CHU
 * @Date: 2018/9/6 11:44
 * @Description:
 */
@Component
@Slf4j
public class SeckillOrderFuture {

    @Autowired
    private SeckillExecuteProcessor seckillExecuteProcessor;


    public SeckillOrderCreateDto prepareSeckillOrder(Integer userId, Integer actId, Integer productId, Integer quantity) {
        final String key = actId + ":" + productId;
        SeckillDto seckillDto = RedisUtil.get(RedisKeyPrefix.SECKILL, key, SeckillDto.class);
        if (seckillDto == null || System.currentTimeMillis() > seckillDto.getEndTime().getTime()) {
            //总开关,减少redis访问
            RedisUtil.hSet(RedisKeyPrefix.SECKILL_OPEN_FLAG,userId ,key, false);
            throw new ChuException("秒杀结束");
        }
        if (System.currentTimeMillis() < seckillDto.getStartTime().getTime()) {
            throw new ChuException("秒杀未开始");
        }
//        if (!isPossibleBuy(userId, key, quantity, seckillDto.getSkuLimitBuy())) {
//            RedisUtil.hSet(RedisKeyPrefix.SECKILL_OPEN_FLAG,userId ,key, false);
//            throw new ChuException("超出会员限购数");
//        }
        if (!hasInventory(userId,key, quantity)) {
            RedisUtil.hSet(RedisKeyPrefix.SECKILL_OPEN_FLAG,userId ,key, false);
            throw new ChuException("秒杀库存不足");
        }
        SeckillOrderCreateDto seckillOrderCreateDto = new SeckillOrderCreateDto();
        seckillOrderCreateDto.setProductId(productId);
        seckillOrderCreateDto.setActId(actId);
        seckillOrderCreateDto.setQuantity(quantity);
        seckillOrderCreateDto.setMemberId(userId);
        seckillOrderCreateDto.setShopId(seckillDto.getShopId());
        return seckillOrderCreateDto;
    }

    private boolean isPossibleBuy(Integer userId, String key, Integer quantity, Integer limitBuy) {
        Integer userPurchasedNum = RedisUtil.hGet(RedisKeyPrefix.SECKILL_RECORD_USER, userId, key);
        if ((userPurchasedNum == null ? 0 : userPurchasedNum) + quantity > limitBuy) {
            log.error("sku:{}超出会员限购数", key);
            return false;
        }
        return true;
    }


    private boolean hasInventory(Integer userId,String key, Integer quantity) {
        AtomicBoolean flag = new AtomicBoolean(true);
        Integer inventory = RedisUtil.get(RedisKeyPrefix.SECKILL_STOCKS, key, Integer.class);
        if (inventory < quantity) {
            log.error("当前秒杀商品:{},当前库存:{}不足", key,inventory);
            flag = new AtomicBoolean(false);
            return flag.get();
        }
        String stocKey = RedisKeyPrefix.SECKILL_STOCKS.getPrefix() + key;
        long decr = RedisUtil.decr(stocKey, quantity);
        if (decr < 0) {
            flag = new AtomicBoolean(false);
        }
        return flag.get();
    }

    public CompletableFuture<String> execute(SeckillOrderCreateDto seckillOrderCreateDto) {
        return CompletableFuture.supplyAsync(() -> {
            Message<SeckillOrderCreateDto> message = MessageBuilder.withPayload(seckillOrderCreateDto).build();
            seckillExecuteProcessor.output().send(message);
            return "排队中";
        });
    }
}
